package com.ck.ips.schedule;

import com.ck.common.model.OperationLog;
import com.ck.common.model.Program;
import com.ck.core.constant.BusinessConstant;
import com.ck.core.constant.device.DeviceSettingType;
import com.ck.core.constant.ModuleConstant;
import com.ck.core.constant.program.ProgramStatusEnum;
import com.ck.core.lock.LockConstant;
import com.ck.core.lock.RedisDistributeLock;
import com.ck.core.lock.RedisLock;
import com.ck.ips.service.DeviceService;
import com.ck.ips.service.program.ProgramService;
import com.ck.ips.service.sys.OperationLogService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author linqiang
 * @version v1.0
 * @Description 节目状态检查任务
 * @date 2019-05-10 10:55
 */
@Component
public class ProgramStatusCheckJob {
    private Logger logger = LoggerFactory.getLogger(ProgramStatusCheckJob.class);

    @Autowired
    private ProgramService programService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private RedisDistributeLock distributeLock;


    /**
     * 检查节目状态(每分钟执行)
     */
    @Async
    //@Scheduled(cron = "0 0/1 * * * ?")
    public void checkProgramStatus() {
        logger.info(">>> 开始检查节目状态");
        StopWatch stopwatch = new StopWatch();
        stopwatch.start();
        //查询有效的，待播放和播放中的节目
        try (RedisLock lock = distributeLock.getLock((LockConstant.CHECK_PROGRAM_STATUS_JOB_LOCK_PREFIX),
                LockConstant.DEFAULT_TIMEOUT_MILLS, LockConstant.MAX_RETRY_TIMES, LockConstant.RETRY_INTERVAL_TIME_MILLIS)) {
            if (null != lock) {
                List<Program> programList = programService.getToPlayAndPlayingPrograms();
                if (CollectionUtils.isNotEmpty(programList)) {
                    List<String> overTimeVersionList = new ArrayList<>();
                    for (Program program : programList) {
                        int deviceProgramCount = programService.countDeviceProgramByProgramVersion(program.getProgramVersion());
                        if (deviceProgramCount == 0) {
                            //已从终端下线该节目
                            overTimeVersionList.add(program.getProgramVersion());
                            continue;
                        }
                        if (null != program.getPutinEndTime()) {
                            //节目投放结束时间小于当前时间
                            if (program.getPutinEndTime() < System.currentTimeMillis()) {
                                overTimeVersionList.add(program.getProgramVersion());
                            }
                        }
                    }
                    if (CollectionUtils.isNotEmpty(overTimeVersionList)) {
                        //批量更新节目为‘已过期’
                        long updateTime = System.currentTimeMillis();
                        programService.batchUpdateStatus(ProgramStatusEnum.EXPIRED, overTimeVersionList, updateTime);

                        String versions = Arrays.toString(overTimeVersionList.toArray());
                        logger.info(">>> 批量更新节目为已过期，节目版本号 : " + versions);

                        //添加操作日志
                        operationLogService.saveOperationLog(createSuccessOperationLog(ModuleConstant.MODULE_PROGRAM,
                                ">>> 批量更新节目为已过期，节目版本号 : " + versions, updateTime));
                        //根据节目版本号查询节目终端deviceCode集合
                        List<String> deviceCodeList = deviceService.listDeviceCodeByProgramVersion(overTimeVersionList);
                        if (CollectionUtils.isNotEmpty(deviceCodeList)) {
                            //批量将过期节目信息更新到缓存中的终端
                            deviceService.flushDeviceStateCache(DeviceSettingType.PROGRAM_UPDATE, deviceCodeList, updateTime);
                            logger.info(">>> 节目过期，刷新缓存，节目版本号：" + versions);
                            //添加操作日志
                            operationLogService.saveOperationLog(createSuccessOperationLog(ModuleConstant.MODULE_PROGRAM,
                                    ">>> 节目过期，刷新设备缓存，节目版本号：" + versions, updateTime));
                        }
                    }
                    logger.info(">>> 检查节目状态成功");
                }
                stopwatch.stop();
                logger.info(">>> 完成检查节目状态，耗时：" + stopwatch.getTotalTimeMillis() + "ms");
            } else {
                logger.warn(">>> 检查节目状态失败:网络繁忙");
            }
        } catch (Exception e) {
            logger.error(">>> 检查节目状态失败: " + e.getMessage());
        }
    }

    /**
     * 构建成功操作日志
     *
     * @param module     模块
     * @param content    内容
     * @param updateTime 操作时间
     * @return OperationLog
     */
    private OperationLog createSuccessOperationLog(String module, String content, Long updateTime) {
        OperationLog operationLog = new OperationLog();
        operationLog.setOperationModule(module);
        operationLog.setOperationContent(content);
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(updateTime);
        return operationLog;
    }
}
